home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xbomb-2.0 / xbomb-2 / xbomb / xbomb.c < prev    next >
C/C++ Source or Header  |  1995-11-16  |  9KB  |  442 lines

  1. /***************************************
  2.   $Header: /home/amb/xbomb/RCS/xbomb.c 1.9 1995/11/16 20:16:39 amb Exp $
  3.  
  4.   XBomb - 'Minesweeper' game - Version 2
  5.  
  6.   Main function of program - excludes all window interface parts.
  7.  
  8.   Written by Andrew M. Bishop
  9.  
  10.   This file Copyright 1994 1995 Andrew M. Bishop
  11.   It may be distributed under the GNU Public License, version 2, or
  12.   any higher version.  See section COPYING of the GNU Public license
  13.   for conditions under which this file may be redistributed.
  14.   ***************************************/
  15.  
  16.  
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <time.h>
  21. #include <ctype.h>
  22. #include "xbomb.h"
  23.  
  24. #if defined(__sun__) && !defined(__svr4__)
  25. int printf(const char*, ... );
  26. int tolower (int c);
  27. time_t time(time_t *t);
  28. int rand(void);
  29. #endif
  30.  
  31. static int count_adjacent(int x,int y,int flag);
  32.  
  33. int grid_width,grid_height,grid_bombs,grid_level,grid_type;
  34.  
  35. char levels[NLEVELS][LEVELSLEN]=LEVELS;
  36. char types [NTYPES] [TYPESLEN] =TYPES;
  37. int widths [NLEVELS]=WIDTHS;
  38. int heights[NLEVELS]=HEIGHTS;
  39. int nbombs [NLEVELS]=NBOMBS;
  40.  
  41. static int status=GAME_WAIT;
  42.  
  43. static unsigned char state[MAX_SIZE][MAX_SIZE];
  44. static int n_unseen,n_think,ticks;
  45.  
  46. /*++++++++++++++++++++++++++++++++++++++
  47.   The main program.
  48.  
  49.   int argc The command line parameters.
  50.  
  51.   char** argv The command line parameters.
  52.   ++++++++++++++++++++++++++++++++++++++*/
  53.  
  54. void main(int argc,char** argv)
  55. {
  56.  int level=0,type=GAME_SQUARE;  /* Default values. */
  57.  int xstatus=0;
  58.  long t;
  59.  
  60.  printf("\n                XBomb Version 2\n                ---------------       (c) AMB Software 1995\n\n");
  61.  
  62.  if(argc>1)
  63.    {
  64.     int i,j;
  65.  
  66.     for(j=0;j<NLEVELS;j++)
  67.       {
  68.        char levstr[3];
  69.        sprintf(levstr,"-%1d",j+1);
  70.        for(i=1;i<argc;i++)
  71.           if(!strcmp(levstr,argv[i]))
  72.              level=j;
  73.       }
  74.  
  75.     for(j=0;j<NTYPES;j++)
  76.       {
  77.        char typstr[TYPESLEN+1];
  78.        sprintf(typstr,"-%s",types[j]);
  79.        for(i=1;i<strlen(typstr);i++)
  80.           typstr[i]=tolower(typstr[i]);
  81.        for(i=1;i<argc;i++)
  82.           if(!strncmp(typstr,argv[i],strlen(argv[i])))
  83.              type=GAME_TYPE+j;
  84.       }
  85.  
  86.     for(i=1;i<argc;i++)
  87.        if(strlen(argv[i])>2 && !strncmp("-hiscore",argv[i],strlen(argv[i])))
  88.          {
  89.           grid_type=type;
  90.           PrintHighScores(-1);
  91.           exit(0);
  92.          }
  93.    }
  94.  
  95.  t=time(&t);
  96.  
  97.  srand((unsigned int)t);
  98.  
  99.  InitialiseX(&argc,argv);
  100.  
  101.  StartGame(level,type);
  102.  
  103.  for(;;)
  104.    {
  105.     xstatus=ProcessXEvents();
  106.  
  107.     if(xstatus==GAME_QUIT)
  108.        break;
  109.     else
  110.        if(xstatus==GAME_START)
  111.          {
  112.           if(status==GAME_CONTINUES)
  113.              StopGame();
  114.           StartGame(level,type);
  115.          }
  116.        else
  117.           if(xstatus>=GAME_LEVEL && xstatus<(GAME_LEVEL+NLEVELS))
  118.              level=xstatus-GAME_LEVEL;
  119.           else
  120.              if(xstatus>=GAME_TYPE && xstatus<(GAME_TYPE+NTYPES))
  121.                 type=xstatus;
  122.  
  123.     switch(status)
  124.       {
  125.       case GAME_WON:
  126.        StopGame();
  127.        printf("WON! on %s level of %s\n",levels[grid_level],types[grid_type-GAME_TYPE]);
  128.        AddHighScore(grid_level,ticks);
  129.        break;
  130.       case GAME_LOST:
  131.        StopGame();
  132.        printf("LOST! on %s level of %s\n",levels[grid_level],types[grid_type-GAME_TYPE]);
  133.        break;
  134.       default:;
  135.       }
  136.    } 
  137.  
  138.  FinishUpX();
  139. }
  140.  
  141.  
  142. /*++++++++++++++++++++++++++++++++++++++
  143.   Start a new game.
  144.  
  145.   int level The level of the game to play.
  146.  
  147.   int type The type of game to play.
  148.   ++++++++++++++++++++++++++++++++++++++*/
  149.  
  150. void StartGame(int level,int type)
  151. {
  152.  int x,y;
  153.  
  154.  grid_type=type;
  155.  grid_level=level;
  156.  grid_width=widths[level];
  157.  grid_height=heights[level];
  158.  grid_bombs=nbombs[level];
  159.  
  160.  n_unseen=grid_width*grid_height;
  161.  n_think=0;
  162.  
  163.  status=GAME_READY;
  164.  
  165.  for(x=0;x<grid_width;x++)
  166.     for(y=0;y<grid_height;y++)
  167.        state[x][y]=UNSEEN;
  168.  
  169.  ScaleWindow();
  170.  DrawGrid();
  171.  StartClock(0);
  172.  SetUXB(grid_bombs);
  173. }
  174.  
  175.  
  176. /*++++++++++++++++++++++++++++++++++++++
  177.   Hides the bombs in the grid.
  178.  
  179.   int xs The location that has no neighbouring bombs.
  180.  
  181.   int ys The location that has no neighbouring bombs.
  182.   ++++++++++++++++++++++++++++++++++++++*/
  183.  
  184. void HideBombs(int xs,int ys)
  185. {
  186.  int i,x,y;
  187.  
  188.  state[xs][ys]+=CORRECT;
  189.  
  190.  for(i=0;i<grid_bombs;i++)
  191.    {
  192.     do{
  193.        x=(rand()>>8)%grid_width;
  194.        y=(rand()>>8)%grid_height;
  195.       }
  196.     while(state[x][y]!=UNSEEN || count_adjacent(x,y,CORRECT));
  197.  
  198.     state[x][y]+=ACTUAL_BOMB;
  199.    }
  200.  
  201.  state[xs][ys]-=CORRECT;
  202.  
  203.  for(x=0;x<grid_width;x++)
  204.     for(y=0;y<grid_height;y++)
  205.        if(!(state[x][y]&ACTUAL_BOMB))
  206.           state[x][y]+=count_adjacent(x,y,ACTUAL_BOMB);
  207.  
  208.  StartClock(1);
  209. }
  210.  
  211.  
  212. /*++++++++++++++++++++++++++++++++++++++
  213.   Stop the game.
  214.   ++++++++++++++++++++++++++++++++++++++*/
  215.  
  216. void StopGame(void)
  217. {
  218.  status=GAME_WAIT;
  219.  ticks=StopClock();
  220. }
  221.  
  222. /*++++++++++++++++++++++++++++++++++++++
  223.   Draws the grid at the start of the game or for expose events.
  224.   ++++++++++++++++++++++++++++++++++++++*/
  225.  
  226. void DrawGrid(void)
  227. {
  228.  int x,y;
  229.  
  230.  for(x=0;x<grid_width;x++)
  231.     for(y=0;y<grid_height;y++)
  232.        DrawSquare(x,y,state[x][y]);
  233. }
  234.  
  235. /*++++++++++++++++++++++++++++++++++++++
  236.   The function that is called when a single square is selected.
  237.  
  238.   int x The location of the square.
  239.  
  240.   int y The location of the square.
  241.   ++++++++++++++++++++++++++++++++++++++*/
  242.  
  243. void SelectSquare(int x,int y)
  244. {
  245.  if(!(state[x][y]&UNSEEN) || state[x][y]&THINK_BOMB || status==GAME_WAIT)
  246.     return;
  247.  
  248.  if(status==GAME_READY)
  249.    {
  250.     HideBombs(x,y);
  251.     status=GAME_CONTINUES;
  252.    }
  253.  
  254.  RemoveEmpties(x,y);
  255.  
  256.  if(state[x][y]&ACTUAL_BOMB)
  257.    {
  258.     int x,y;
  259.  
  260.     for(x=0;x<grid_width;x++)
  261.        for(y=0;y<grid_width;y++)
  262.           if(state[x][y]&UNSEEN)
  263.             {
  264.              state[x][y]&=~UNSEEN;
  265.              if(state[x][y]&THINK_BOMB && state[x][y]&ACTUAL_BOMB)
  266.                 state[x][y]|=CORRECT;
  267.             }
  268.           else
  269.              state[x][y]|=CORRECT;
  270.  
  271.     status=GAME_LOST;
  272.     DrawGrid();
  273.    }
  274.  else
  275.    {
  276.     DrawSquare(x,y,state[x][y]);
  277.  
  278.     if(n_think==n_unseen)
  279.        status=GAME_WON;
  280.    }
  281. }
  282.  
  283.  
  284. /*++++++++++++++++++++++++++++++++++++++
  285.   Select all of the squares adjacent
  286.  
  287.   int x The location of the square.
  288.  
  289.   int y The location of the square.
  290.   ++++++++++++++++++++++++++++++++++++++*/
  291.  
  292. void SelectAdjacent(int x,int y)
  293. {
  294.  int dx,dy,n,dd=(grid_type==GAME_TRIANGLE?2:1);
  295.  
  296.  if(state[x][y]&UNSEEN || status==GAME_WAIT)
  297.     return;
  298.  
  299.  n=count_adjacent(x,y,THINK_BOMB);
  300.  
  301.  if(state[x][y]!=n)
  302.     return;
  303.  
  304.  for(dx=-dd;dx<=dd;dx++)
  305.    {
  306.     if((x+dx)<0 || (x+dx)>=grid_width)
  307.        continue;
  308.  
  309.     for(dy=-1;dy<=1;dy++)
  310.       {
  311.        if((y+dy)<0 || (y+dy)>=grid_height)
  312.           continue;
  313.        if(dx==0 && dy==0)
  314.           continue;
  315.  
  316.        if(grid_type==GAME_HEXAGON && dy!=0 && dx==(1-2*(y%2)))
  317.           continue;
  318.        if(grid_type==GAME_TRIANGLE && dy==(2*((x+y)%2)-1) && (dx==-2 || dx==2))
  319.           continue;
  320.  
  321.        if(!(state[x+dx][y+dy]&THINK_BOMB))
  322.           SelectSquare(x+dx,y+dy);
  323.       }
  324.    }
  325. }
  326.  
  327.  
  328. /*++++++++++++++++++++++++++++++++++++++
  329.   Marks as a bomb the square.
  330.  
  331.   int x The location of the square.
  332.  
  333.   int y The location of the square.
  334.   ++++++++++++++++++++++++++++++++++++++*/
  335.  
  336. void MarkBomb(int x,int y)
  337. {
  338.  if(!(state[x][y]&UNSEEN) || status==GAME_WAIT)
  339.     return;
  340.  
  341.  if(n_think==grid_bombs && !(state[x][y]&THINK_BOMB))
  342.     return;
  343.  
  344.  state[x][y]^=THINK_BOMB;
  345.  
  346.  if(state[x][y]&THINK_BOMB)
  347.     n_think++;
  348.  else
  349.     n_think--;
  350.  
  351.  SetUXB(grid_bombs-n_think);
  352.  
  353.  DrawSquare(x,y,state[x][y]);
  354.  
  355.  if(n_think==n_unseen)
  356.     status=GAME_WON;
  357. }
  358.  
  359. /*++++++++++++++++++++++++++++++++++++++
  360.   Removes the empty squares around here
  361.  
  362.   int x Start from this position.
  363.  
  364.   int y Start from this position.
  365.   ++++++++++++++++++++++++++++++++++++++*/
  366.  
  367. void RemoveEmpties(int x, int y)
  368. {
  369.  int dx,dy,dd=(grid_type==GAME_TRIANGLE?2:1);
  370.  
  371.  if(!(state[x][y]&UNSEEN) || state[x][y]&THINK_BOMB)
  372.     return;
  373.  
  374.  state[x][y]&=~UNSEEN;
  375.  n_unseen--;
  376.  DrawSquare(x,y,state[x][y]);
  377.  
  378.  if(state[x][y]!=EMPTY)
  379.     return;
  380.  
  381.  for(dx=-dd;dx<=dd;dx++)
  382.    {
  383.     if((x+dx)<0 || (x+dx)>=grid_width)
  384.        continue;
  385.  
  386.     for(dy=-1;dy<=1;dy++)
  387.       {
  388.        if((y+dy)<0 || (y+dy)>=grid_height)
  389.           continue;
  390.        if(dx==0 && dy==0)
  391.           continue;
  392.  
  393.        if(grid_type==GAME_HEXAGON && dy!=0 && dx==(1-2*(y%2)))
  394.           continue;
  395.        if(grid_type==GAME_TRIANGLE && dy==(2*((x+y)%2)-1) && (dx==-2 || dx==2))
  396.           continue;
  397.  
  398.        RemoveEmpties(x+dx,y+dy);
  399.       }
  400.    }
  401. }
  402.  
  403.  
  404. /*++++++++++++++++++++++++++++++++++++++
  405.   Count the number of adjacent squares that are bombs.
  406.  
  407.   int count_adjacent Returns the number of adjacent bombs.
  408.  
  409.   int x The position to start from.
  410.  
  411.   int y The position to start from.
  412.  
  413.   int flag The type of bomb to look for.
  414.   ++++++++++++++++++++++++++++++++++++++*/
  415.  
  416. static int count_adjacent(int x,int y,int flag)
  417. {
  418.  int n=0,dx,dy,dd=(grid_type==GAME_TRIANGLE?2:1);
  419.  
  420.  for(dx=-dd;dx<=dd;dx++)
  421.    {
  422.     if((x+dx)<0 || (x+dx)>=grid_width)
  423.        continue;
  424.  
  425.     for(dy=-1;dy<=1;dy++)
  426.       {
  427.        if((y+dy)<0 || (y+dy)>=grid_height)
  428.           continue;
  429.  
  430.        if(grid_type==GAME_HEXAGON && dy!=0 && dx==(1-2*(y%2)))
  431.           continue;
  432.        if(grid_type==GAME_TRIANGLE && dy==(2*((x+y)%2)-1) && (dx==-2 || dx==2))
  433.           continue;
  434.  
  435.        if(state[x+dx][y+dy]&flag)
  436.           n++;
  437.       }
  438.    }
  439.  
  440.  return(n);
  441. }
  442.